 PAG
*********************************
*  SEGTHREEFONE
*********************************

 ORG $C800  ;CODE RUNS HERE

* THIS SPACE IS SHARED WITH THE VIA AND THE RAM.

 HEX 00  ;NEED THIS BYTE SO $C7FF IS NOT REFERENCED,
    ; TO MAKE WORK IN SLOT #7

********************************
*  TABLE2
* NUMBER CONTAINS PROCESSOR AND
* ADDRESS MODE INFO. LOCATION
* IN MATRIX IS OPCODE.
********************************

* BITS  7  6 5  4 3 2 1 0
*       R  T T  ADDRESS MODE
*       E  Y Y  0 TO $16
*       S  P P
*       E  E E
*       R  0 0= 6502
*       V  0 1= 65C02
*       E  1 0= 65802 & 65816
*       D  1 1= RESERVED
*       0 = ALWAYS

* ADDRESS MODES

* $MODE BYTES SYMBOL ADDRESS
*   0    2-3    #      IMED
*   1     3     a      ABS
*   2     4     al     ABS.L
*   3     2     d      DIR
*   4     1   i or S   ACC;IMP;STK
*   5     2   (d),y    DIR.IND.INX
*   6     2   [d],y    DIR.IND.L.INX
*   7     2   (d,x)    DIR.INX.IND
*   8     2    d,x     DIR.INX.W/X
*   9     2    d,y     DIR.INX.W/Y
*   A     3    a,x     ABS.INX.W/X
*   B     4    al,x    ABS.L.INX.W/X
*   C     3    a,y     ABS.INX.W/Y
*   D     2     r      P.C.REL
*   E     3     rl     P.C.REL.L
*   F     3    (a)     ABS.IND.
*  10     2    (d)     DIR.IND.
*  11     2    [d]     DIR.IND.L
*  12     3   (a,x)    ABS.INX.IND
*  13     2    d,s     STK.REL
*  14     2   (d,s),y  STK.REL.IND.INX
*  15     2     s      STK
*  16     3    b,b     XYZ

* SPECIAL NOTES

* PER - rl ; PEI - (d) ; PEA - a
* REP & SEP - 2 BYTES ALWAYS
* BRK - 1 BYTES IN 6502 & C02 AND 2 BYTES IN 65816 & 802.

TABLE2 EQU *

*       LSD -->  0 1 2 3 4 5 6 7 8 9 A B C D E F

 HEX 04075553230303510400044421010142
 HEX 0D05305423080846040C2444210A0A4B
 HEX 01074253030303510400044401010142
 HEX 0D05305428080846040C24442A0A0A4B
 HEX 04074453560303510400044401010142
 HEX 0D05305456080846040C2444420A0A4B
 HEX 04074E5323030351040004440F010142
 HEX 0D05305428080846040C2444320A0A4B
 HEX 2D074E53030303510420044401010142
 HEX 0D05305408080946040C0444210A2A4B
 HEX 00070053030303510400044401010142
 HEX 0D05305408080946040C04440A0A0C4B
 HEX 00074053030303510400042401010142
 HEX 0D05305450080846040C24244F0A0A4B
 HEX 00074053030303510400044401010142
 HEX 0D05305441080846040C2444520A0A4B

********************************
*  TABLE3
* EACH 2 BYTE NUMBER REPRESENTS
* THE SYMBOLS DISPLAYED AND THE
* NUMBER OF BYTES FOR THAT MODE
********************************

* BIT # --> 7 6 5 4 3 2 1 0 7  6  5 4 3  2 1 0 
*SYMBOL --> 0 0 # ( [ a x x 0 ,S ,X ] ) ,Y { e

* a = 1 DISPLAY BYTES AS IS
* a = 0 DISPLAY RELATIVE ADDRESS

* xx = NUMBER OF BYTES IN INSTRUCTION - 1 
* 00 = 1, 01 = 2, 10 = 3, 11 = 4

* { = 0 NO ADDRESS DISPLAYED
* { = 1 DISPLAY ADDRESS

* e = 0 RELATIVE OFFSET OR NO ADDRESS
* e = 1 EFFECTIVE ADDRESS

TABLE3 EQU *

* START WITH MODE 0

 DDB %0010010100000000
 DDB %0000011000000011
 DDB %0000011100000000
 DDB %0000010100000011
 DDB %0000010000000000
 DDB %0001010100001111
 DDB %0000110100010111
 DDB %0001010100101011
 DDB %0000010100100011
 DDB %0000010100000111
 DDB %0000011000100011
 DDB %0000011100100011
 DDB %0000011000000111
 DDB %0000000100000010
 DDB %0000001000000010
 DDB %0001011000001011
 DDB %0001010100001011
 DDB %0000110100010011
 DDB %0001011000101011
 DDB %0000010101000011
 DDB %0001010101001111
 DDB %0000010100000000
 DDB %0000011000000000
TBL3END

********************************
* MNEMONIC TABLE
* CONTAINS MNEMONICS COMPRESSED
* INTO 2 BYTES.
********************************

MNEMTABL

*ADC
 HEX 0483
*AND 
 HEX 05C4
*ASL
 HEX 066C
*BCC
 HEX 0863
*BCS
 HEX 0873
*BEQ
 HEX 08B1
*BIT
 HEX 0934
*BMI
 HEX 09A9
*BNE
 HEX 09C5
*BPL
 HEX 0A0C
*BRA
 HEX 0A41
*BRK
 HEX 0A4B
*BRL
 HEX 0A4C
*BVC
 HEX 0AC3
*BVS
 HEX 0AD3
*CLC
 HEX 0D83
*CLD
 HEX 0D84
*CLI
 HEX 0D89
*CLV
 HEX 0D96
*CMP
 HEX 0DB0
*COP
 HEX 0DF0
*CPX
 HEX 0E18
*CPY
 HEX 0E19
*DEC
 HEX 10A3
*DEX
 HEX 10B8
*DEY
 HEX 10B9
*EOR
 HEX 15F2
*INC
 HEX 25C3
*INX
 HEX 25D8
*INY
 HEX 25D9
*JML
 HEX 29AC
*JMP
 HEX 29B0
*JSL
 HEX 2A6C
*JSR
 HEX 2A72
*LDA
 HEX 3081
*LDX
 HEX 3098
*LDY
 HEX 3099
*LSR
 HEX 3272
*MVN
 HEX 36CE
*MVP
 HEX 36D0
*NOP
 HEX 39F0
*ORA
 HEX 3E41
*PEA
 HEX 40A1
*PEI
 HEX 40A9
*PER
 HEX 40B2
*PHA
 HEX 4101
*PHB
 HEX 4102
*PHD
 HEX 4104
*PHK
 HEX 410B
*PHP
 HEX 4110
*PHX
 HEX 4118
*PHY
 HEX 4119
*PLA
 HEX 4181
*PLB
 HEX 4182
*PLD
 HEX 4184
*PLP
 HEX 4190
*PLX
 HEX 4198
*PLY
 HEX 4199
*REP
 HEX 48B0
*ROL
 HEX 49EC
*ROR
 HEX 49F2
*RTI
 HEX 4A89
*RTL
 HEX 4A8C
*RTS
 HEX 4A93
*SBC
 HEX 4C43
*SEC
 HEX 4CA3
*SED
 HEX 4CA4
*SEI
 HEX 4CA9
*SEP
 HEX 4CB0
*STA
 HEX 4E81
*STP
 HEX 4E90
*STX
 HEX 4E98
*STY
 HEX 4E99
*STZ
 HEX 4E9A
*TAX
 HEX 5038
*TAY
 HEX 5039
*TCD
 HEX 5064
*TCS
 HEX 5073
*TDC
 HEX 5083
*TRB
 HEX 5242
*TSB
 HEX 5262
*TSC
 HEX 5263
*TSX
 HEX 5278
*TXA
 HEX 5301
*TXS
 HEX 5313
*TXY
 HEX 5319
*TYA
 HEX 5321
*TYX
 HEX 5338
*WAI
 HEX 5C29
*WDM
 HEX 5C8D
*XBA
 HEX 6041
*XCE
 HEX 6065

* ASSEMBLER DIRECTIVES

*HEX
 HEX 20B8

*ADR
 HEX 0492

****************************************
* THIS POINT MUST BE $CA00 OR ABOVE.
****************************************

 DS $CA00-*,$FF

***** TABLE4 *****
* POSSIBLE SYMBOLS USED IN OPERAND

 HEX 00  ;SO DOESN'T LOOK LIKE 2 BYTE SYMBOL
TABLE4
 ASC "#",00
 ASC "(",00
 ASC "[",00
 ASC ",S",00
 ASC ",X",00
 ASC "]",00
 ASC ")",00
 ASC ",Y",00

********************************
*  MINI ASSEMBLER
********************************

COMDMA EQU *

 BEQ MANOADDR ;IF NO ADDRESS FOLLOWS
 JSR LOADMEM  ;GET ADDRESS
 BCC MANOADDR ;ADDRESS OK
 LDA #BADPAR  ;BAD PARAMETER ERROR NUMBER
ERREXIT3
 JSR TRANSFR3 ;INVALID ADDRESS
 DFB ERRBEEPC ;CODE
 JMP MAIN103

MANOADDR
 JSR DISASM  ; DISPLAY INSTRUCTION
 LDX #19  ;SPACES
 JSR TRANSFR3
 DFB PRBL2C  ;CODE
 LDA #"!"
 STA PROMPT  ;NEW PROMPT
 JSR TRANSFR3 ;GET INPUT LINE
 DFB GETLNC  ;CODE
 BCC :NOESC
 JMP MAIN103 ;if "esc" key
:NOESC INX  ;X=0 IF ONLY <CR> ENTERED
 LDY #00
 JSR TRANSFR3 ;GET FIRST CHARACTER
 DFB GETCHRC  ;CODE
 BNE MACHKCOM ;CHECK INPUT

* ONLY CR ENTERED SO GO TO NEXT INSTRUCTION
* NUMDISP = # OF BYTES IN INSTRUCTION-1

 LDY NUMDISP
MAINCMEM
 JSR INCMEMLH ;INC MEM POINTER
 DEY
 BPL MAINCMEM
 BMI MANOADDR ;GO TO NEXT INSTRUCTION

MACHKCOM
 CMP #":"  ;RETURN TO COMMAND LEVEL?
 BNE MASTLET1 ;IF NO
 JMP MAIN103  ;IF YES
MASTLET1
 STA MNEMCOMP ;TEMP SAVE

* CAUSE ERROR IF A SOFT BREAK IS AT THIS LOCATION

 STY TEMP+1  ;SAVE Y
* LETTER 1,2,3 USED BY VALIDAD
 LDA MEMHI
 STA LETTER2  ;USED BY VALIDAD
 LDA MEMLOW
 STA LETTER1
 JSR TRANSFR3 ;IS THIS LOCATION A REAL BREAK?
 DFB VALIDADC ;CODE
 BNE :OK  ;IF NO
 JMP MANOTRAM ;IF REAL BRK, DISPLAY **ACCESS ERROR**
:OK LDY TEMP+1  ;RESTORE Y

 LDA MNEMCOMP ;RESTORE
 ASL MNEMCOMP+1 ;MAKE BIT 0 = 0
 JSR PACKMNEM ;PACK 1ST LETTER OF MNEMONIC
 JSR TRANSFR3 ;
 DFB GETCHRC  ;CODE
 BEQ MAERR
 JSR PACKMNEM ;PACK 2ND LETTER
 JSR TRANSFR3 ;
 DFB GETCHRC  ;CODE
 BEQ MAERR
 JSR PACKMNEM ;PACK 3RD LETTER
 STX XBUFF

*MNEMCOMP & MNEMCOMP+1 CONTAIN 2 BYTE MNEMONIC IN COMPRESSED
*FORM.
*COMPARE WITH COMPRESSED MMEMONICS IN MNEMTABL

 LDX #0
FINDMNEM
 LDA MNEMCOMP
 CMP $C800  ;SELECT EXT ROM
 CMP MNEMTABL,X ;DO THEY MATCH?
 STA $CF00  ;ENABLE EXT RAM
 BNE NEXTMNEM ;IF NO, TRY NEXT MNEM
 LDA MNEMCOMP+1
 CMP $C800
 CMP MNEMTABL+1,X ;DO BOTH BYTES MATCH?
 STA $CF00
 BEQ FOUNDMNE ;IF YES

NEXTMNEM
 INX
 INX
 CPX #$BC  ;OUT OF MNEMONICS?
 BLT FINDMNEM ;IF NO

* IF OUT OF MNEMONICS OR OTHER ERROR, COME HERE.

MAERROP LDY #10  ;OPCODE ERROR
MAERR TYA
 CLC
 ADC #11  ;POSITION UNDER ERROR
 TAX
 JSR TRANSFR3 ;PRINT SPACES (X REG)
 DFB PRBL2C  ;CODE
 LDA #"^"
 JSR COUT3  ;INDICATE WHERE ERROR WAS
 JSR TRANSFR3 ;PRINT "ERR" RING BELL
 DFB PRERRC  ;code
 JSR TRANSFR3 ;<RETURN>
 DFB CROUTC  ;code
 JMP MANOADDR ;TRY AGAIN

* FOUND THE MNEMONIC IN MNEMTABL

FOUNDMNE
 STX OPCODE  ;USE OPCODE AS TEMP STORAGE FOR # OF MNEMONIC

*BUILD A 2 BYTE NUMBER OF DISPLAY INFO, AS IN TABLE 3

 LDA #0
 STA MODE  ;TEMP BUFFER
 STA OPERAND
 LDA #02  ;SET BIT USED AS FINISHED FLAG
 STA OPERAND+1 ;FORM 2 BYTES HERE
CHEKSYMB
 LDX XBUFF  ;GET STRING POINTER
FROMADRS
 JSR TRANSFR3 ;GET CHAR
 DFB GETCHRC  ;CODE
 STX XBUFF
 LDX MODE  ;TABLE4 POINTER
 CMP TABLE4,X
 BEQ ISSYMB

*SYMBOLS DON'T MATCH

 DEY
 INC XBUFF  ;TRY SAME CHAR AGAIN
 LDA TABLE4-1,X ;WAS IT A 2 BYTE SYMBOL
 BEQ CLRSHFT  ;IF NO
 DEY   ;IF YES, BACKUP TO 1ST CHARACTER
 INC XBUFF
CLRSHFT CLC
 BCC SHFTSYMB ;<ALWAYS>

*SYMBOLS DO MATCH

ISSYMB 
 LDA TABLE4+1,X ;IS IT TWO BYTE SYMBOL?
 BNE INCSYMB  ;IF YES, BOTH BYTES MUST MATCH
 SEC
SHFTSYMB
 ROL OPERAND+1
 ROL OPERAND
 BMI SYMBDONE ;FLAG BIT IS IN BIT7

 CPX #19  ;OUT OF SYMBOLS TO CHECK?
 BGE CLRSHFT  ;IF YES, KEEP SHIFTING TILL DONE

*INC TABLE4 POINTER TO NEXT SYMBOL

 INX
 INX
 LDA TABLE4,X
 BNE NEXTSYM
INCSYMB INX
NEXTSYM
 STX MODE

*IS ADDRESS NEXT

 CPX #$6  ;CHECK FOR ADDRESS?
 BNE CHEKSYMB

*IS ADDRESS
*CHECK FOR HEX DATA & READ 

 LDX XBUFF  ;GET STRING POINTER
 JSR TRANSFR3 ;READ NUMBER, START AT CURRENT CHAR
 DFB CHKREADAC ;code
 INC INLENGTH
 LSR INLENGTH ;CONVERT TO # OF BYTES IN ADDRESS
 LDA OPERAND+1
 SEC
 ROL   ;ALWAYS SET BIT2 OF 1ST BYTE
 ASL
 ASL
 ORA INLENGTH ;BIT 7 OF BYTE 2 IS ALWAYS 0
 ASL
 STA OPERAND+1 ;INCLUDE # OF BYTES INFO
 ROL OPERAND
 DEY
 INX
 JMP FROMADRS

*ASSEMBLER INPUT ERROR

TOMAERR JMP MAERR

*THE TWO BYTES REPRESENTING THE MODE OF THE INSTRUCTION
*ARE FINISHED. FIND THE POSSIBLE MODES OF THE INSTRUCTION.
*THE RELATIVE INSTRUCTIONS; BEQ $34, MAY LOOK LIKE MODE #3
*BEQ $0034 WILL LOOK LIKE MODE #1. MODE #E WILL LOOK LIKE
*MODE #2 SOME MODES LOOK THE SAME TRY FOR EXACT MATCH,
*IF MODE OF MNEM. & THIS MODE DON'T MATCH TRY TO MATCH IN
*TABLE3 WITH DIFFERENT MODE(SOME LOOK THE SAME)
*IF STILL NO MATCH WITH MNEM. OR IN TABLE3, THEN MAYBEE IS
*RELATIVE INSTRUCTION. SET BIT 2 OF 1ST BYTE TO 0 AND TRY
*FOR MATCH, IF NO MATCH, DECREASE # OF BYTES (BITS 0 & 1)
*BY 1 AND TRY AGAIN.

*FIND THE OPCODE OF THE INSTRUCTION BY MATCHING THE
*MODE OF THE INPUT OPERAND WITH THE MODE OF THE INPUT MNEM.

SYMBDONE
 LDX #8  ;SET UP FOR DISPLAYING GENERATED CODE
 JSR SPACES  ;ALIGN WITH PREVIOUS CODE

 JSR FINDOPCD ;LOOK FOR OPCODE
 BCC FOUNDOP  ;OPCODE IN OPCODE BUFFER, MODE IN MODE

* NO MATCH FOUND BETWEEN MNEM MODES & OPERAND MODE
* TRY LOOKING AT RELATIVE MODES WITH Z PAGE DESTINATIONS
* OR RELATIVE LONG.

 LDA OPERAND
 AND #%00111011 ;SET BITS 7, 6, & 2 TO 0
 STA OPERAND
 JSR FINDOPCD ;LOOK FOR OPCODE
 BCC RELATIVE ;FOUND IT. RELATIVE INST.

*NO MATCH TRY LOOKING AT ALL OTHER RELATIVE MODES

 LDA #%00111100
 BIT OPERAND
 BNE LOOKDIR  ;NOT RELATIVE MODE SO LOOK FOR DIRECTIVE
 DEC OPERAND  ;REDUCE # OF BYTES BY 1 TO MATCH RELATIVE
 JSR FINDOPCD
 BCC RELATIVE ;FOUND IT RELATIVE INST.

*-----------------------------------------------
* NOT ABLE TO MATCH MNEM MODES WITH OPERAND MODE
* SO LOOK FOR ASSEMBLER DIRECTIVE

LOOKDIR LDX OPCODE  ;GET MNEMONIC NUMBER
 CPX #$B8  ;IS IT HEX?
 BNE :CKADR  ;IF NO
 LDA #1  ;1 BYTE OF HEX DATA
 BNE ADRHEX
:CKADR CPX #$BA  ;IS IT ADR?
 BNE TOMAERR  ;IF NOT MUST BE MA ERROR
 LDA #2  ;2 BYTES OF ADR DATA
 BNE ADRHEX  ;<ALWAYS>

*----------------------------------
***** RELATIVE MODE ***** 

RELATIVE
 JSR INCMEMLH ;CONVERT ADDRESS TO RELATIVE OFFSET
 JSR INCMEMLH

* OFFSET IS CALCULATED FROM ADDRESS OF INSTRUCTION
* FOLLOWING THE BRANCH OPERAND
* SUBTRACT MEMLOW & MEMHI FROM TEMP+1 & TEMP+2, WHICH SHOULD 
* GIVE ME THE BRANCH OFFSET

 LDA MODE  ;IS IT REL. LONG
 CMP #$E*2  ;MODE IS TIMES 2
 CLC
 BEQ RELLONG  ;IF YES, SUBTRACT AN EXTRA 1
 SEC
RELLONG LDA LETTER1  ;LOW BYTE OF OPERAND ADDRESS
 SBC MEMLOW
 STA LETTER1
 LDA LETTER2  ;HI BYTE OF OPERAND
 SBC MEMHI
 STA LETTER2
 BNE BNCHBACK ;IF NOT 0 MUST BE BRANCHING BACKWARD
 BIT LETTER1  ;IF FORWARD BRANCH LOW BYTE CAN'T BE NEGATIVE
 BMI BRNCHOUT ;IF IT IS THEN BRANCH IS OUT OF RANGE
 BPL OFFSETOK ;IF OK
BNCHBACK
 CMP #$FF
 BNE BRNCHOUT ;THE MSBYTE MUST BE $00 OR $FF
 BIT LETTER1  ;IF BRANCHING BACKWARD BYTE CAN'T BE POSITIVE
 BPL BRNCHOUT
OFFSETOK
 JSR DECMEMLH ;DEC MEMLOW & MEMHI
 JSR DECMEMLH

* PUT THE INSTRUCTION INTO RAM
* FOUND THE PROPER OP CODE

FOUNDOP LDA OPCODE
 JSR INITMMV  ;INIT LOWADD W/MEMLOW, STA, LDA, VERIFY
 BNE MANOTRAM ;STORE, Z BIT SET IF VERIFY OK
 JSR BYTESP3  ;DISPLAY CODE BYTE & SPACE
 JSR INCMEMLH ;INC MEMLOW & MEMHI POINTERS

 LDX MODE  ;MODE IS TIMES 2
 CMP $C800  ;DISABLE EXT RAM
 LDA TABLE3,X
 CMP $CF00  ;ENABLE EXT RAM
 AND #$03  ;# OF BYTES IN OPERAND

* ENTER HERE IF ASSEMBLER DIRECTIVE
ADRHEX STA INLENGTH ;USED BY STOROPER
 BEQ MANEXT  ;MUST BE IMPLIED
 LDX #0

* STORE INLENGTH NUMBER OF BYTES
STOROPER
 LDA LETTER1,X
 JSR INITMMV
 BNE MAERRBY2 ;LOCATION NOT RAM
 JSR BYTESP3  ;DISPLAY ACC & SPACE
 JSR INCMEMLH
 INX
 CPX INLENGTH
 BLT STOROPER


* DISASSEMBLE THE NEXT INSTRUCTION

MANEXT JSR TRANSFR3 ;CARRIAGE RETURN
 DFB CROUTC  ;code
 JMP MANOADDR

MAERRBY3
 JSR DECMEMLH ;DEC MEMLOW & MEMHI
MAERRBY2
 JSR DECMEMLH
MANOTRAM
 JSR TRANSFR3 ;DISPLAY "**ACCESS ERROR**"
 DFB DISNOTRMC ;CODE
 JMP MANEXT

BRNCHOUT
 LDA MODE  ;IF REL LONG
 CMP #$E*2  ;MODE IS TIMES 2
 BEQ OFFSETOK
 JSR TRANSFR3 ;
 DFB PRERRC  ;CODE
 JSR TRANSFR3 ;DISPLAY "BRANCH OUT OF RANGE"
 DFB DISBROUTC ;CODE
 JSR DECMEMLH
 JSR DECMEMLH
 JMP MANEXT

*****************************************
*   DISASM   
* DISASSEMBLE THE CURRENT INSTRUCTION 
* MEMLOW & MEMHI CONTAIN THE PROGRAM COUNTER LO & HI BYTES
* MEMPBR CONTAINS THE PROGRAM BANK REGISTER.
***************************************** 

* USE CURRENT MEMPBR

DISASM JSR TRANSFR3 ;MEM DISPLAY
 DFB DSMEMCOLC ;code
 LDX #0
 LDY #0
 JSR GETBYTE  ;GET OPCODE
 STA OPCODE  
 TAY   ;USED AS POINTER FOR TABLE3
 CMP $C800  ;DISABLE EXT RAM
 LDA TABLE2,Y ;INSTRUCTIONS ADDRESS MODE & PC TYPE
 CMP $CF00  ;ENABLE EXT RAM
 AND #$60  ;ISOLATE PC TYPE
 BEQ TYPEOK  ;IF 6502 MUST BE OK
 CMP #$20  ;IS IT 65C02 INSTRUCTION?
 BNE CHK816  ;IF NO, MUST BE 816
 LDA CMOSFLAG ;IS THE 65C02 ALLOWED?
 BNE TYPEOK  ;IF NOT RESTRICTED TO 65C02, IT IS OK
 JMP MAKENOP  ;INVALID INSTRUCTION ???
CHK816 BIT CMOSFLAG ;IS 65816 ALLOWED?
 BVS TYPEOK  ;IF YES
 JMP MAKENOP  ;INVALID INSTRUCTION ???

TYPEOK CMP $C800  ;DISABLE EXT RAM
 LDA TABLE2,Y ;GET ADD. MODE & VALID PC INFO
 CMP $CF00  ;ENABLE EXT RAM
 AND #$1F  ;LEAVE ONLY ADD. MODE INFO
 ASL   ; TIME 2
 TAY   ;ADDRESS MODE TIMES 2 (OFFSET TO TABLE3)
 STA MODE
 CMP $C800  ;DISABLE EXT RAM
 LDA TABLE3,Y ;GET # OF BYTES & DISPLAY INFO
 CMP $CF00  ;ENABLE EXT RAM
 AND #$03  ;GET # OF BYTES IN INSTRUCTION
 TAX
 TYA   ;TEST FOR # MODE Y=0?
 BNE SVNUMBYT ;IF NOT
*8 OR 16 BIT
 BIT CMOSFLAG ;IS 65802 OR 816 MODE ON
 BVC SVNUMBYT ;IF NO THEN 8 BIT
 LDA OPCODE
 AND #$0F
 CMP #$09  ;IS OPCODE ACCUMULATOR INSTRUCTION
 BNE CHK16X  ;IF NO, CHECK FOR 16 BIT INDEX
* CHECK FOR 16 BIT DATA
 BIT MFLAG  ;BIT 7 = 1 IF 16 BIT DATA
 BPL SVNUMBYT ;IF 8 BIT
 BMI SIXTEEN  ;IF 16 BIT
CHK16X BIT MFLAG  ;BIT 6 = 1 IF 16 BIT INDEX
 BVC SVNUMBYT ;IF 8 BIT 
SIXTEEN INX   ;16 BIT DATA SO DISPLAY 3 BYTES

SVNUMBYT
 STX NUMDISP  ;# OF BYTES TO DISPLAY-1
 LDY #0  ;SET FOR GETBYTE
 STY MLIFLAG  ;0=MLI CALL, MAKE <> 0 IF NOT MLI
 JSR DISPBYTS ;DISPLAY THE HEX FORM OF INSTRUCTION

*PRINT MNEMONIC

 LDX OPCODE

*GET OFFSET THAT POINTS TO COMPRESSED MNEMONIC
 JSR TRANSFR3 ;LDA TABLE1,X
 DFB LTABLE1C ;CODE
 TAX
 CMP $C800
 LDA MNEMTABL,X ;GET UPPER HALF OF COMP' MNEM
 CMP $CF00
 STA MNEMCOMP
 CMP $C800
 LDA MNEMTABL+1,X ;GET LOWER HALF OF COMP' MNEM
 CMP $CF00
 STA MNEMCOMP+1

* UNPACK THE 2 BYTE MNEMONIC & DISPLAY

 LDX #3
UNPACK LDA MNEMCOMP
 LSR
 LSR
 AND #%00011111 ;LETTER
 CLC
 ADC #$C0
 JSR COUT3  ;
 JSR LEFT5 ;SHIFT MNEMCOMP LEFT 5 TIMES
 DEX
 BNE UNPACK

 LDA #$A0
 JSR COUT3  ;SPACE

*DISPLAY THE REST OF THE INSTRUCTION
 LDY MODE  ;GET OFFSET TO TABLE3
 CMP $C800  ;DISABLE EXT RAM
 LDA TABLE3,Y ;GET THE 1ST BYTE OF DISPLAY INFO
 CMP $CF00  ;ENABLE EXT RAM
 ASL
 ASL
 LDX #0
NEXTSYMB
 ASL
 PHA   ;SAVE
 BCC NOSYMBOL
GETSYMB 
 LDA TABLE4,X ;GET THE SYMBOL
 BEQ SYMBEND  ;0=STOP
 JSR COUT3  ;DISPLAY SYMBOL
 INX
 BNE GETSYMB
NOSYMBOL
 INX
 LDA TABLE4,X
 BNE NOSYMBOL
SYMBEND INX
 PLA
 CPX #6  ;DISPLAY ADDRESS?
 BNE :NO ;IF NO
 JMP DISPADDR ;YES
:NO CPX #19  ;DISPLAY EFFECTIVE ADD.?
 BLT NEXTSYMB ;IF NO
 ASL   ;DISPLAY EFFECTIVE ADD?
 BCC :LEAVE  ;IF NO
 PHA
 LDA #$A0
 JSR COUT3  ;
 LDA #"{"
 JSR COUT3  ;
 PLA
 ASL   ;EFFECTIVE ADDRESS?
 BCC RELADDRS ;IF NO
 JSR TRANSFR3 ;CALC EFFECTIVE ADDRESS
 DFB CALCEFFC ;code
* DISPLAY EFFECTIVE ADDRESS
 LDA EFFADRS+2
 JSR TRANSFR3
 DFB PRBYTEC  ;code
 LDA EFFADRS+1
 LDX EFFADRS
 JSR TRANSFR3
 DFB PRNTAXC  ;code

*------------------
* CHECK FOR MLI CALL

 LDA MLIFLAG  ;WAS THIS AN MLI CALL ?
 BNE :LEAVE  ;IF NO
 JSR TRANSFR3 ;DO <CR>
 DFB CROUTC  ;code
 LDX #8
 JSR SPACES  ;6 SPACES
 LDX #2  ;# OF BYTES-1
 LDY #3
 JSR DISPBYTS ;DISPLAY THE 3 BYTES OF MLI STUFF
 LDX #4
 JSR SPACES  ;4 SPACES, RETURNS WITH X=0
 STX MLIFLAG  ;CLEAR AGAIN AFTER DISPBYTS
 LDY #3
 JSR GETBYTE
 JSR TRANSFR3 ;PRINT MLI CODE BYTE
 DFB PRBYTEC
 LDA #$A0
 JSR COUT3  ;SPACE
 INY
 JSR GETBYTE
 TAX
 INY
 JSR GETBYTE
 JSR TRANSFR3 ;PRINT MLI ADDRESS
 DFB PRNTAXC
 LDX NUMDISP
 INX
 INX   ;INC NUMDISP TO REFLECT
 INX   ;3 XTRA BYTES OF MLI
 STX NUMDISP
:LEAVE JMP ENDDISAS

*NOT EFFECTIVE ADDRESS SO INDICATE RELATIVE OFFSET

RELADDRS
 LDA #0
 STA TEMP+1
 LDY NUMDISP  ;# BYTES IN INSTRUCTION-1
 JSR GETBYTE  ;LOAD HI ORDER BYTE OF OFFSET. OP LO HI
 STA TEMP
 DEY
 BEQ ONEBYTE
 JSR GETBYTE  ;GET LO BYTE OF OFFSET
 STA TEMP+1
ONEBYTE LDA TEMP  ;GET HI BYTE OR ONLY BYTE
 BPL POSOFSET ;POSITIVE OFFSET

*TAKE 2'S COMPLIMENT OF NEG OFFSET
 LDA #0
 SEC
 SBC TEMP+1  ;TEMP+1 IS 0 FOR 1 BYTE OFFSET
 STA TEMP+1  ;AND WILL NOT AFFECT THE CARRY FLAG
 LDA #0
 SBC TEMP
 STA TEMP  ;2'S COMP. FINISHED
 LDA #"-"
 BNE DISPSIGN
POSOFSET
 LDA #"+"
DISPSIGN
 JSR COUT3  ;DISPLAY SIGN OF OFFSET
 LDA TEMP
 JSR TRANSFR3 ;PRINT ACC AS 2 HEX DIGITS
 DFB PRBYTEC  ;CODE
 TYA   ;TEST Y
 BEQ OFFSTEND ;ONE BYTE OFFSET
 LDA TEMP+1  ;LOW BYTE OF OFFSET
 JSR TRANSFR3 ;DISPLAY AS 2 HEX DIGITS
 DFB PRBYTEC  ;CODE
OFFSTEND
 LDA #"}"
 JSR COUT3  ;
 JMP ENDDISAS ;END OF DISASSEMBLY


*DISPLAY THE ADDRESS BYTES OF THE INSTRUCTION (E.G. LDA #$XX)

DISPADDR
 ASL   ;TEST BIT 2 FROM TABLE 3 (RELATIVE ADDR.?)
 BCS DISPASIS ;DISPLAY ADDRESS AS IS

*CALCULATE RELATIVE ADDRESS
*OUR PCHI & PCLO IS POINTING AT THE CURRENT INSTRUCITON.
* BUT A BRANCH OFFSET WORKS OFF THE FOLLOWING INSTRUCTIONS PC.
* SO ADD THE NUMBER OF BYTES IN THE BRANCH INSTRUCTION
* (2 OR 3) TO THE OFFSET

 LDA #0
 STA TEMP+1  ;HI BYTE
 LDY NUMDISP  ;# BYTES IN INSTRUCTION-1

*GET 1 BYTE OFFSET OR HI BYTE OF 2 BYTE OFFSET 
 JSR GETBYTE
 CPY #2
 BEQ TWOBYTE
 STA TEMP  ;ONLY USED FOR 8 BIT OFFSET
 ORA #00  ;SET FLAGS
 BPL NOEXTEND ;IF POS # DO NOT SIGN EXTEND
 LDA #$FF
TWOBYTE STA TEMP+1  ;SIGN EXTEND 8 BIT NEG OFFSET, OR HI BYTE
NOEXTEND DEY  ;DEC. INSTRUCTION POINTER
 BEQ ONEOFFST ;IF NOT BYTE OFFSET
 JSR GETBYTE
 STA TEMP

*ADD THE NUMBER OF BYTES IN THE BRANCH INSTRUCTION
* TO THE OFFSET. ADD OFFSET TO PC & DISPLAY ADDRESS

ONEOFFST
 SEC   ;ADD IN CARRY BECAUSE NUMDISP IS 1 LESS
 LDA TEMP  ;THAN # OF BYTES
 ADC NUMDISP
 PHP   ;SAVE CARRY
 CLC
 ADC MEMLOW  ;ADD TO PC
 TAX
 LDA MEMHI
 ADC #0  ;ADD IN CARRY FROM MEMLOW IF ANY
 PLP   ;GET CARRY FROM NUMDISP IF ANY
 ADC TEMP+1  ;ADD IN HI BYTE OFFSET
 JSR TRANSFR3 ;DISPLAY ADDRESS
 DFB PRNTAXC  ;CODE
 JMP T3BYTE2  ;GET BYTE2 FROM TABLE3

*DISPLAY THE ADDRESS BYTES AS IS

DISPASIS

 LDY NUMDISP  ;# BYTES IN INSTRUCTION-1
 BEQ T3BYTE2  ;ONLY 1 BYTE INSTRUCTION

 LDA MODE  ;SKIP IF # MODE
 BEQ DISPAS2

* CLEAR EFFADRS
 LDA #0
 LDY #2
:NEXT STA EFFADRS,Y
 DEY
 BNE :NEXT
 LDY NUMDISP

DISPAS2 JSR GETBYTE  ;GET THE HIGHEST ORDER ADDRESS BYTE
 LDX MODE  ;DON'T CHANGE EFF IF # MODE
 BEQ :NOEFF  ;IF #
 STA EFFADRS-1,Y ;SAVE FOR EFFECTIVE ADDRS.
:NOEFF JSR TRANSFR3 ;PRINT THE BYTE
 DFB PRBYTEC  ;CODE
 DEY
 BNE DISPAS2  ;NEXT BYTE

*LOAD 2ND BYTE FROM TABLE3 DISPLAY INFO

T3BYTE2 LDY MODE  ;OFFSET TO TABLE3
 CMP $C800  ;DISABLE EXT RAM
 LDA TABLE3+1,Y ;GET 2ND BYTE OF DISPLAY INFO
 CMP $CF00  ;ENABLE EXT RAM
 ASL   ;BIT 7 EMPTY
 LDX #6  ;RESET X
 JMP NEXTSYMB ;CONTINUE DISPLAYING INSTRUCTION

*DISPLAY "???"

MAKENOP TYA   ;OPCODE
 JSR TRANSFR3 ;DISPLAY OPCODE
 DFB PRBYTEC  ;code
 LDX #10
 JSR TRANSFR3 ;LINE UP
 DFB PRBL2C  ;code
 LDX #3
PRINT? LDA #"?"
 JSR COUT3  ;
 DEX
 BNE PRINT?
 STX NUMDISP  ;# OF BYTES - 1

EFFADDRS   ;<<<TEMPORARY>>>

*---------------------------------
*  END DISASSEMBLE ROUTINE
*---------------------------------

ENDDISAS
 JSR TRANSFR3 ;RETURN
 DFB CROUTC  ;code
 RTS   ;END OF DISASSEMBLY



********* SUBROUTINES **********


*-----------------------------------
* DISPLAY THE HEX FORM OF THE INSTRUCTION
* SET MLIFLAG TO NON 0 IF NOT JSR $BF00
* ENTER WITH X=NUMBER OF BYTES-1
*
* SPACES ENTRY POINT DISPLAYS X NUMBER OF SPACES
*-----------------------------------

* MLI CODE FOR COMPARISON
MLICODE JSR $BF00

DISPBYTS
 JSR GETBYTE
 CMP MLICODE,Y ;DOES IT MATCH MLI CALL?
 BEQ :MAYBE  ;THIS PART MATCHES
 INC MLIFLAG  ;NOT AN MLI CALL
:MAYBE JSR BYTESP3  ;PRINT ACC AS HEX BYTE & SPACE
 INY
 DEX
 BPL DISPBYTS
 LDX NUMDISP  ;# OF BYTES DISPLAYED-1
 INX

*PRINT PROPER NUMBER OF SPACES SO ALL MNEMONICS LINE UP
 LDA #12
:LOOP SEC
 SBC #3
 BEQ DBYTEEND ;NO SPACES
 DEX
 BNE :LOOP
 TAX   ;# OF SPACES TO PRINT

*-------------------------------
* ALTERNATE ENTRY POINT

SPACES JSR TRANSFR3 ;PRINT X NUMBER OF SPACES
 DFB PRBL2C  ;CODE
DBYTEEND
 RTS

*--------------------------------
* PRINT THE ACC AS 1 HEX BYTE FOLLOWED BY 1 SPACE

BYTESP3 JSR TRANSFR3 ;
 DFB PRBYTEC  ;CODE
 LDA #$A0  ;SPACE

*-----------------------------

COUT3 JSR TRANSFR3
 DFB COUTC
 RTS

*------------------------------

* DECREMENT MEMLOW BY 1
DECMEMLH
 SEC
 LDA MEMLOW
 SBC #1
 STA MEMLOW
 LDA MEMHI
 SBC #0
 STA MEMHI
 RTS

*FINDOPCD SUBROUTINE
*COMPARE THE OPERAND OF THE INPUT INSTRUCTION WITH
* THE OPERAND OF EACH MODE IN TABLE 3
*IF A MATCH IS FOUND THEN CHECK TABLE 2 TO SEE IF
* THE MNEMONIC IS AVAILABLE IN THAT MODE.
*IF IT IS THEN SAVE MODE IN MODE & OPCODE IN OPCODE

FINDOPCD
 LDX #TBL3END-TABLE3-2 ;1ST BYTE OF LAST MODE
NEWOPER CMP $C800
 LDA TABLE3+1,X ;GET BYTE2 OF OPCODE FLAGS
 CMP $CF00
 AND #$FC  ;IGNORE BITS 0 & 1
 CMP OPERAND+1 ;DOES INPUT OPERAND MATCH?
 BNE NEXTOPER ;IF NO
 LDA OPERAND
 AND #$3F  ;IGNORE BITS 6 & 7
 CMP $C800
 CMP TABLE3,X ;DO MODES MATCH?
 STA $CF00
 BNE NEXTOPER ;IF NO

*OPERAND MODES MATCH. NOW SEE IF MNEM IS AVAILABLE IN THIS MODE

 STX MODE  ;SAVE POSSIBLE (MODE x 2)
 LDX #$0
POSIBLOP
 JSR TRANSFR3 ;LDA TABLE1,X
 DFB LTABLE1C ;CODE
 CMP OPCODE  ;COMPARE WITH MNEMONIC THAT WAS SAVED HERE
 BEQ CHKMODE
NEXTOPCD
 INX
 BNE POSIBLOP

*TRY NEXT OPERAND FROM TABLE3

 LDX MODE  ;RESTORE X
NEXTOPER
 DEX
 DEX   ;GOTO NEXT ENTRY IN TABLE 3
 BPL NEWOPER

*OPCODE NOT FOUND

INVPROC SEC   ;SET ERROR CONDITION
 RTS

*FOUND POSSIBLE OP CODE, SEE IF MODES MATCH

CHKMODE CMP $C800  ;DISABLE EXT RAM
 LDA TABLE2,X ;GET MODE INFO FOR THIS OPCODE
 CMP $CF00  ;ENABLE EXT RAM
 AND #$1F  ;STRIP UNUSED STUFF
 ASL   ;TIMES 2 BECAUSE MODE IS TIMES 2
 CMP MODE  ;DO MODES MATCH, IF SO FOUND OPCODE
 BNE NEXTOPCD ;IF NO

*FOUND OPCODE. IS IT PROCESSOR TYPE THAT IS ALLOWED.

 STX OPCODE  ;SAVE
 CMP $C800  ;DISABLE EXT RAM
 LDA TABLE2,X ;GET INFO ON THIS OPCODE
 CMP $CF00  ;ENABLE EXT RAM
 AND #$60  ;STRIP ALL BUT PROCESSOR INFO
 BEQ PROCESOK ;IF 00=6502, MUST BE OK
 BIT CMOSFLAG ;IS 65816 ALLOWED?
 BVS PROCESOK ;IF YES, MUST BE OK
 BPL INVPROC  ;IF 6502 ONLY, THEN INVALID
 CMP #$20  ;IS INSTR 65C02?
 BNE INVPROC  ;IF NO, INVALID

*OPCODE IS ALLOWED

PROCESOK
 CLC   ;CLEAR ERROR FLAG
 RTS

* INIT LOWADD & HIADD WITH MEMLOW & MEMHI
* STORE THE CONTENTS OF THE ACC. & VERIFY THAT IT STORED
* PROPERELY RETURNS WITH Z BIT SET IF VERIFIED OK.

INITMMV EQU *
 LDY MEMPBR
 STY PBRADD
 LDY MEMHI
 STY HIADD
 LDY MEMLOW
 STY LOWADD
 PHA
 LDY #0
 JSR TRANSFR3 ;STA LOWADD,Y
 DFB STAINDYC ;CODE
 JSR TRANSFR3 ;LDA LOWADD,Y
 DFB LDAINDYC ;CODE
 STA TEMP
 PLA   ;DID IT STORE PROPERELY?
 CMP TEMP
 RTS

* INCREMENT MEMLOW & MEMHI POINTER BY 1

INCMEMLH
 CLC
 LDA MEMLOW
 ADC #1
 STA MEMLOW  ;INC POINTER
 LDA MEMHI
 ADC #0
 STA MEMHI
 RTS

* LOAD MEMLOW & MEMHI, CARRY SET ON ERROR

LOADMEM EQU *
 JSR TRANSFR3 ;CHECK FOR HEX AND READ
 DFB CHKREADC ;CODE
 BCS LOADMRTS ;CARRY SET FOR ERROR
 STA MEMLOW
 LDA LETTER2  ;LOAD POINTER
 STA MEMHI
LOADMRTS
 RTS

***** PACK THE MNEMONIC INTO 2 BYTES *****
*
* MNEMCOMP & MNEMCOMP+1 WILL CONTAIN THE COMPRESSED MNEMONIC
* EXAMPLE:  ADC  A= $C1 AND WITH #$1F = %00001
*                D= $C4  "   "     "  = %00100
*                C= $C3  "   "     "  = %00011
*   0 00001 00100 00011 = $0483 COMPRESSED FORM OF ADC
*
PACKMNEM
 JSR LEFT5
 AND #$1F
 ORA MNEMCOMP+1
 STA MNEMCOMP+1
 RTS

LEFT5 STX XBUFF
 LDX #5
:LEFT ASL MNEMCOMP+1
 ROL MNEMCOMP
 DEX
 BNE :LEFT
 LDX XBUFF
 RTS

* GET THE BYTE POINTED TO BY LOWADD,Y

GETBYTE JSR TRANSFR3 ;GET BYTE FROM PROGRAM RAM
 DFB LDAINDYC ;CODE
 RTS

******* SAVE THE ACC, X AND P REGISTERS *****

SAVEAXP3
 PHP   ;SAVE STATUS
 STX XSAVESEG
 STA ASAVESEG
 PLA
*GET STATUS
 STA PSAVESEG ;SAVE
 RTS

****** RESTORE THE ACC, X AND P REGISTERS *****

RESTAXP3
 LDX XSAVESEG
 LDA PSAVESEG
 PHA
 LDA ASAVESEG
 PLP
 RTS

***** THIS SEGMENTS GLOBAL SUBROUTINES *****

SUBTABL3

INITMMVC EQU *-SUBTABL3*4+3+$100
 DA INITMMV-1

DECMEMLHC EQU *-SUBTABL3*4+3+$100
 DA DECMEMLH-1

INCMEMLHC EQU *-SUBTABL3*4+3+$100
 DA INCMEMLH-1

LOADMEMC EQU *-SUBTABL3*4+3+$100
 DA LOADMEM-1

DISASMC EQU *-SUBTABL3*4+3+$100
 DA DISASM-1

**********************************
***** SEGMENT CROSSOVER AREA *****
**********************************

 LST ON
S3END = $CF9D-*
 do nolist
 LST OFF
 fin
 ERR *-1/$CF9D
 DS $CF9D-*,$FF

MAIN103 JSR SAVEAXP3 ;COME HERE TO TRANSFER TO SEGMENT0 DIRECTLY
 LDX SLOTN0
 LDA #%00000101 ;RAM0,ROM5
 STA SEGMBASE,X ;NEXT INSTRUCTION EXECUTED FROM SEGMENT 5
 JSR RESTAXP3 ;RESTORE AFTER TRANSFER FROM SEGMENT 5
 RTS  ;GOTO COMMANDS IN THIS SEGMENT
 NOP
 NOP  ;MATCH LENGTH WITH SEG 5

* TRANSFER TO OTHER SEGMENTS

TRANSFR3

 JSR SAVEAXP3
 PLA   ;GET RETRUN ADDRESS FROM STACK
 CLC
 ADC #1  ;INC TO POINT AT CODE BYTE
 STA TEMPSEG  ;SETUP LDA TEMPSEG ROUTINE
 PLA
 ADC #0  ;ADD CARRY, IF ANY
 STA TEMPSEG+1 ;SETUP LDA TEMPSEG ROUTINE
 PHA
 LDA TEMPSEG
 PHA   ;BUMP RETURN ADDRESS PAST CODE BYTE
 LDA #3  ;CURRENT SEG #
 PHA
 JSR LDATEMP  ;LOAD CODE BYTE
 STA SEGMCODE ;SAVE CODE
 AND #$07  ;STRIP ALL BUT SEG #
 LDX SLOTN0
 STA SEGMBASE,X ;NEXT INSTR. RUN FROM NEW SEGMENT
* NEW SEGMENT
 LDA #>RETURN3 ;WHERE TO RETURN TO
 PHA
 LDA #RETURN3
 PHA
 LDA SEGMCODE ;CODE BYTE
 AND #$F8  ;STIP OFF SEG# LEAVING SUB #
 LSR
 LSR   ;LEAVE SUB# MULTIPLIED BY 2
* GET ADDRESS OF SUB FROM SUBTABL & PUSH ON STACK
 TAX
 LDA SUBTABL3+1,X
 PHA
 LDA SUBTABL3,X
 PHA

 JSR RESTAXP3 ;RESTORE REGISTERS
 RTS   ;USE RTS TO GOTO SUB

* RETURN HERE FROM SUBROUTINE

RETURN3 EQU *-1
 JSR SAVEAXP3
 PLA   ;SEG # TO RETURN TO
 LDX SLOTN0
 STA SEGMBASE,X ;RETURN TO SEGMENT
 JSR RESTAXP3
 RTS   ;RETURN TO PROGRAM

 DS \,$FF ;PUT OBJECT AT NEXT PAGE
